home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / fpu881 / src6.zoo / atof.c < prev    next >
C/C++ Source or Header  |  1991-09-24  |  4KB  |  159 lines

  1. /* M.R's kludgy atof --- 881 version.        */
  2. /*     uses long integer accumulators and extended precision to put them    */
  3. /*    together in the fpu. The conversion long to extended is done completely    */
  4. /*    on the 881.    */
  5.  
  6. /* 12.7.1989, 11.10.90, 28.1.91 */
  7. /* On overflow, only +-infinity is returned (the 68881's default),      */
  8.  
  9. #include <ctype.h>
  10. #include <stdio.h>
  11. #include <math.h>
  12. #include <errno.h>
  13.  
  14. #define    true 1
  15. #define false 0
  16. #define CharIsDigit ( isdigit(*Text) )
  17. #define Digit ((*Text-'0'))
  18.  
  19. double atof( const char * );
  20. double exp10( double );
  21. double strtod( const char *, const char ** );
  22. double _Float_( long, long, long, long );
  23.  
  24. #if 0
  25. static unsigned long
  26.     __notanumber[2] = { 0x7fffffffL, 0xffffffffL }; /* ieee NAN */
  27. #define NAN  (*((double *)&__notanumber[0]))
  28. #endif 0
  29.  
  30. #define ten_mul(X)    ((((X) << 2) + (X)) << 1)
  31.  
  32. double strtod( const char * Save, const char ** Endptr )
  33. {
  34.   register int Count; int Negative = false, ExpNegative = false;
  35.  
  36.   double Value;
  37.   register long Exponent, Exp_Temp;
  38.   register long Value_1, Value_2;
  39.   register char c;
  40.   register char * Text;
  41.   register char * Places;
  42.   char Buffer[15];
  43.  
  44.   Text = Save;
  45.   Places = Buffer;
  46.  
  47.   /* skip over leading whitespace */
  48.   while (isspace(*Text)) Text++;
  49.  
  50.   if (*Text == '-') {
  51.     Negative = true;
  52.     Text++;
  53.   } else
  54.   if (*Text == '+') {
  55.     Negative = false;
  56.     Text++;
  57.   } else
  58.   if( *Text == 0 ) {
  59.     if( Endptr != NULL ) *Endptr = Text;
  60.     return 0.0;
  61.   }
  62.  
  63.   /* Process the 'f'-part */
  64.   /* ignore any digit beyond the 15th */
  65.  
  66.   Exp_Temp = 0;    /* needed later on for the exponential part    */
  67.   Value_1 = 0; Value_2 = 0; Count = 0; Exponent = 0;
  68.   while( CharIsDigit ) {    /* process digits before '.' */
  69.     if( Count < 15 ) {
  70.       Count++;
  71.       *Places++ = Digit;
  72.     }
  73.     Text++;
  74.   }
  75.   if ( *Text == '.') {
  76.     Text++;
  77.     while( CharIsDigit ) {    /* process digits after '.' */
  78.       if( Count < 15 )    {
  79.         Count++;
  80.             *Places++ = Digit;
  81.         Exponent--;
  82.       }
  83.       Text++;
  84.     }
  85.   }
  86.   Places = Buffer;
  87.  
  88.   /* Now, Places points to a vector of <= 15 integer numbers                */
  89.   /* text points to the position immediately after the end of the mantissa    */
  90.   /* Value_2 will contain the equiv. of the 8 least significant digits, while            */
  91.   /* Value_1 will contain the equiv. of the 7 most significant digits (if any)        */
  92.   /* and therefore has to be multiplied by 10^8                        */
  93.  
  94.   while( Count > 8 )    {
  95.       Value_1 = ten_mul( Value_1 );      Value_1 += *Places++;
  96.       Count--;
  97.   }
  98.   while( Count > 0 )    {
  99.       Value_2 = ten_mul( Value_2 );      Value_2 += *Places++;
  100.       Count--;
  101.   }
  102.  
  103.   /* 'e'-Part */
  104.   if ( *Text == 'e' || *Text == 'E' || *Text == 'd' || *Text == 'D' ) {
  105.  
  106.     char * Tail = Text;
  107.     Text++;
  108.  
  109.     /* skip over whitespace since ansi allows space after e|E|d|D */
  110.     while (isspace(*Text)) Text++;
  111.  
  112.     if ( * Text == '-' ) {
  113.         ExpNegative = true;
  114.         Text++;
  115.     } else
  116.     if( * Text == '+' ) {
  117.         ExpNegative = false;
  118.         Text++;
  119.     }
  120.     if( !CharIsDigit ) {
  121.         *Endptr = Tail;    /* take the 'e|E|d|D' as part of the characters    */
  122.         goto Ende;        /* following the number */
  123.     } else {
  124.     /* Exponents may have at most 3 digits, everything beyond this is
  125.        ignored */
  126.         Count = 0;
  127.         while( CharIsDigit && (Count < 3) ) {
  128.             Exp_Temp = ten_mul( Exp_Temp ); Exp_Temp += Digit;
  129.               Count++;
  130.             Text++;
  131.         }
  132.         if( ExpNegative ) Exp_Temp = -Exp_Temp;
  133.         Exponent += Exp_Temp;
  134.      }
  135.   }
  136.   Value = _Float_( Value_1, Exponent+8L, Value_2, Exponent );
  137.   if( Endptr != NULL ) *Endptr = Text;
  138.  
  139. Ende:    
  140.   if( Negative ) {
  141.     Value = -Value;
  142.   }
  143.   return( Value );
  144. #if 0
  145. Error:
  146.   fputs("\njunk number \"",stderr); fputs(Save,stderr); 
  147.   fputs("\" --- returning NAN\n",stderr);
  148.   errno = ERANGE;
  149.   if( Endptr != NULL ) *Endptr = Text;
  150.   return(NAN);    /* == Not A Number (NAN) */
  151. #endif
  152. }
  153.  
  154. double atof( const char * Text )
  155. {
  156.     return(strtod(Text,(char **)NULL));
  157. }
  158.  
  159.